from django.shortcuts import render, HttpResponse
from configCenter import models
from user_system import models as user_models
from utils.auth_manog import auth_manog_done
from configCT.settings import logger
from django.http import JsonResponse
from utils.get_current_token import get_token
from utils.hashlib_done import encryption
from configCT.settings import BASE_DIR
from utils.create_game_config import create_game_config
# 使用深拷贝
from copy import deepcopy
import json
import re
import os


# Create your views here.
@auth_manog_done
def conf_setting_list(request):
    """配置文件中心"""
    project_id = request.session.get("project_id")
    if request.method == "GET":
        if not project_id:
            return HttpResponse("没有选择项目，不可操作")
        conf_setting_lists = models.ConfSettingCenter.objects.filter(b_project_id=project_id).all().order_by(
            "server_id")
        return render(request, "configCT/conf_setting_list.html", {
            "conf_setting_lists": conf_setting_lists
        })

@auth_manog_done
def conf_setting_add(request):
    """添加配置文件"""
    project_id = request.session.get("project_id")
    username = request.session.get("username")
    if request.method == "GET":
        return render(request, "configCT/conf_setting_add.html")

    if request.method == "POST":
        try:
            setting_name = request.POST.get("setting_name")
            server_id = request.POST.get("server_id")
            purpose_id = int(request.POST.get("purpose_id"))
            setting_content = request.POST.get("setting_content")

            # 判断是是否是标准的json格式，否则报错跳出
            json.loads(setting_content)

            # 公共分区配置 只能有一个
            if purpose_id == 2:
                conf_obj = models.ConfSettingCenter.objects.filter(b_project_id=project_id, purpose=2).first()
            else:
                conf_obj = models.ConfSettingCenter.objects.filter(b_project_id=project_id, server_id=server_id).first()
            if not conf_obj:
                models.ConfSettingCenter.objects.create(setting_name=setting_name,
                                                        server_id=server_id,
                                                        purpose=purpose_id,
                                                        setting_content=setting_content,
                                                        b_project_id=project_id)

                # 将配置内容写道json文件
                conf_json_path = os.path.join(BASE_DIR, "static/super_cmdb/agent_file", "conf_json")
                if not os.path.exists(conf_json_path): os.makedirs(conf_json_path)
                conf_json_file_path = os.path.join(conf_json_path, "%s_%s.json" % (project_id, server_id))
                with open(conf_json_file_path, "w", encoding="utf-8") as conf_json_file_obj:
                    conf_json_file_obj.write(setting_content)
                ops_info = "配置中心: 项目id: %s, server_id: %s, %s, 创建成功" % (project_id, server_id, setting_name)
                user_models.OpsLogger.objects.create(log_user=username, log_ops=ops_info)
                message = {"code": 0, "msg": "添加配置文件成功"}
            else:
                message = {"code": 1, "msg": "配置文件已存在/公共分区配置只能有一个"}
        except Exception as e:
            logger.error(e)
            logger.error(
                '异常文件：%s ,异常行号：%s' % (e.__traceback__.tb_frame.f_globals['__file__'], e.__traceback__.tb_lineno))
            message = {"code": 1, "msg": "添加配置文件失败,内容必须为json格式,请优先核对,ERR: %s" % e}
        return JsonResponse(message, json_dumps_params={"ensure_ascii": False, "sort_keys": True, "indent": 4})


@auth_manog_done
def conf_setting_edit(request, conf_setting_id):
    """编辑配置文件"""
    project_id = request.session.get("project_id")
    username = request.session.get("username")
    if request.method == "GET":
        conf_setting_info = models.ConfSettingCenter.objects.filter(b_project_id=project_id, id=conf_setting_id).first()
        setting_content = json.loads(conf_setting_info.setting_content)
        return render(request, "configCT/conf_setting_edit.html", {
            "conf_setting_info": conf_setting_info,
            "setting_content": setting_content
        })
    if request.method == "POST":
        setting_name = request.POST.get("setting_name")
        server_id = int(request.POST.get("server_id"))
        setting_content = request.POST.get("setting_content")
        server_id_list = request.POST.getlist("server_id_list", [])
        game_server_id_list = request.POST.getlist("game_server_id_list", [])
        old_setting_content = models.ConfSettingCenter.objects.get(b_project_id=project_id, server_id=server_id).setting_content
        # 判断此次提交有没有更新setting_content的配置内容
        change = True
        if setting_content == old_setting_content:
            change = False
        try:
            setting_content_json = json.loads(setting_content)
            for cross_server_id, game_server_id_lists in zip(server_id_list, game_server_id_list):
                if cross_server_id and game_server_id_lists:
                    game_server_id_lists = game_server_id_lists.replace(' ', '').strip('[]').split(',')  # str转成list
                    game_server_id_lists = list(map(int, game_server_id_lists))  # 将list元素转成int
                    for cross_style, type_content in setting_content_json.items():
                        if cross_server_id in type_content.keys():
                            setting_content_json[cross_style][cross_server_id]["game_server_id"] = game_server_id_lists
            setting_content = json.dumps(setting_content_json, ensure_ascii=False, sort_keys=True, indent=4)  # 转换成str进行保存
            conf_setting_obj = models.ConfSettingCenter.objects.get(b_project_id=project_id, id=conf_setting_id)
            conf_setting_obj.setting_name = setting_name
            conf_setting_obj.server_id = server_id
            conf_setting_obj.setting_content = setting_content
            conf_setting_obj.save()

            # 将配置内容写到json文件
            conf_json_path = os.path.join(BASE_DIR, "static/super_cmdb/agent_file", "conf_json")
            if not os.path.exists(conf_json_path): os.makedirs(conf_json_path)
            conf_json_file_path = os.path.join(conf_json_path, "%s_%s.json" % (project_id, server_id))
            with open(conf_json_file_path, "w", encoding="utf-8") as conf_json_file_obj:
                conf_json_file_obj.write(setting_content)

            if change:
                # 如果模板有关联游戏服配置，则同步更新游戏服配置
                gameserver_config_list_obj = models.GameServer.objects.filter(b_project_id=project_id,
                                                                              b_template_id=conf_setting_id).all()
                if gameserver_config_list_obj:
                    for gameserver_obj in gameserver_config_list_obj:
                        # 重置模板, 使用深拷贝【字典或列表中有嵌套的情况，浅拷贝同样不会生效】
                        template_json = deepcopy(setting_content_json)

                        game_server_id = gameserver_obj.server_id
                        game_server_ip = gameserver_obj.server_ip
                        game_config = json.loads(gameserver_obj.config_content)
                        # 新服处于第几个服
                        ranking = game_config["yunwei_config"]["ranking"]
                        # 计算新服端口号需要累加的数量
                        append_number = ranking * 3
                        # 不变的配置YUNWEI_CONFIG
                        yunwei_config = game_config["yunwei_config"]

                        # 获取域名
                        DOMAIN_obj = models.DomainList.objects.filter(b_project_id=project_id,ip_address=game_server_ip).last()
                        if DOMAIN_obj:
                            DOMAIN = DOMAIN_obj.complete_domain
                        else:
                            DOMAIN = game_server_ip


                        template_json["yunwei_config"] = yunwei_config

                        # 配置文件处理替换变量，配置端口
                        config_content = create_game_config(models, template_json, append_number, game_server_id, DOMAIN, project_id)

                        # 更新到数据库
                        models.GameServer.objects.filter(b_project_id=project_id, server_id=game_server_id).update(
                            config_content=config_content)

            ops_info = "配置中心: 项目id: %s, server_id: %s, %s, 修改成功" % (project_id, server_id, setting_name)
            user_models.OpsLogger.objects.create(log_user=username, log_ops=ops_info)
            message = {"code": 0, "msg": "修改配置文件成功"}
        except Exception as e:
            logger.error(e)
            logger.error(
                '异常文件：%s ,异常行号：%s' % (e.__traceback__.tb_frame.f_globals['__file__'], e.__traceback__.tb_lineno))
            message = {"code": 1, "msg": "修改配置文件失败,内容必须为json格式,请优先核对,ERR: %s" % e}
        return JsonResponse(message, json_dumps_params={"ensure_ascii": False, "sort_keys": True, "indent": 4})


@auth_manog_done
def conf_setting_detail(request, conf_setting_id):
    """显示配置文件内容"""
    project_id = request.session.get("project_id")
    if request.method == "GET":
        conf_setting_info = models.ConfSettingCenter.objects.filter(b_project_id=project_id, id=conf_setting_id).first()
        setting_content = json.loads(conf_setting_info.setting_content)
        return render(request, "configCT/conf_setting_detail.html",
                      {"conf_setting_info": conf_setting_info, "setting_content": setting_content})


@auth_manog_done
def conf_setting_del(request):
    if request.method == "POST":
        try:
            conf_setting_id = request.POST.get("conf_setting_id")  # 前端传过来的全是字符串
            nums = re.findall(r'\d+', conf_setting_id)  # 匹配user_id组成数组
            if isinstance(nums, list):  # 判断user_id是不是一个list
                for id in nums:
                    # id = int(id)
                    setting_name = models.ConfSettingCenter.objects.filter(id=id).first().setting_name
                    models.ConfSettingCenter.objects.filter(id=id).delete()
                    log_success = "删除配置文件【%s】成功" % setting_name
                    print(log_success)
                    message = {"code": 0, "msg": "删除配置文件成功"}
            else:
                message = {"code": 1, "msg": "删除配置文件失败，没有选择配置项"}
        except Exception as e:
            logger.error(e)
            logger.error(
                '异常文件：%s ,异常行号：%s' % (e.__traceback__.tb_frame.f_globals['__file__'], e.__traceback__.tb_lineno))
            message = {"code": 1, "msg": "删除配置文件失败,ERR: %s" % e}
        return JsonResponse(message, json_dumps_params={"ensure_ascii": False, "sort_keys": True, "indent": 4})

@auth_manog_done
def conf_setting_clone(request):
    project_id = request.session.get("project_id")
    user_id = request.session.get("user_id")
    if request.method == "GET":
        user_obj = user_models.User.objects.get(id=user_id)
        my_project_list_obj = user_obj.project.all().order_by("-name")
        return render(request,"configCT/conf_setting_clone.html", {"my_project_list_obj": my_project_list_obj})
    if request.method == "POST":
        rsg = {'status': 0, 'message': None, 'error': None}
        clone_project_id = request.POST.get("clone_project_id")
        clone_conf_setting_list_obj = models.ConfSettingCenter.objects.filter(b_project_id=clone_project_id).all()
        for clone_conf_setting_obj in clone_conf_setting_list_obj:
            server_id = clone_conf_setting_obj.server_id
            if not models.ConfSettingCenter.objects.filter(b_project_id=project_id, server_id=server_id).first():
                models.ConfSettingCenter.objects.create(
                    setting_name=clone_conf_setting_obj.setting_name,
                    server_id=server_id,
                    setting_content=clone_conf_setting_obj.setting_content,
                    b_project_id=project_id,
                    purpose=clone_conf_setting_obj.purpose
                )
        rsg["message"] = "克隆配置成功"
        return JsonResponse(rsg)

@auth_manog_done
def conf_setting_connectcross(request):
    """跨服连接配置"""
    project_id = request.session.get("project_id")
    if request.method == "POST":
        try:
            gameserver_id = request.POST.get("gameserver_id")  # 前端传过来的全是字符串,游戏服id
            connect_cross_server_id = request.POST.get("cross_server_id")  # 跨服id
            gameserver_id_list = re.findall(r'\d+', gameserver_id)  # 匹配user_id组成数组
            logger.info("游戏服id：%s" % gameserver_id_list)
            logger.info("跨服id：%s" % connect_cross_server_id)
            cross_conf_setting_info_obj = models.ConfSettingCenter.objects.get(b_project_id=project_id, server_id=9999)
            cross_conf_setting_info_temp = cross_conf_setting_info_obj.setting_content
            cross_conf_setting_dict = json.loads(cross_conf_setting_info_temp)
            for cross_style, type_content in cross_conf_setting_dict.items():
                for cross_server_id, cross_server_content in type_content.items():
                    if cross_server_id == connect_cross_server_id:
                        game_server_id = cross_server_content["game_server_id"]
                        if not isinstance(game_server_id, list):
                            game_server_id = []
                        logger.info("%s%s" % (game_server_id, type(game_server_id)))
                        for gameserver_id in gameserver_id_list:
                            gameserver_id = int(gameserver_id)
                            if gameserver_id not in game_server_id:
                                game_server_id.append(gameserver_id)
                        game_server_id.sort()  # 排序
                        logger.info(game_server_id)
                        cross_conf_setting_dict[cross_style][cross_server_id]["game_server_id"] = game_server_id
            cross_conf_setting_dict = json.dumps(cross_conf_setting_dict, ensure_ascii=False, sort_keys=True, indent=4)
            # cross_conf_setting_dict = cross_conf_setting_dict.replace("'", '"')
            # logger.info(cross_conf_setting_dict)
            cross_conf_setting_info_obj.setting_content = cross_conf_setting_dict
            cross_conf_setting_info_obj.save()
            message = {"code": 0, "msg": "跨服配置成功"}
        except Exception as e:
            logger.error(e)
            logger.error(
                '异常文件：%s ,异常行号：%s' % (e.__traceback__.tb_frame.f_globals['__file__'], e.__traceback__.tb_lineno))
            message = {"code": 1, "msg": "跨服配置失败,ERR: %s" % e}
        return JsonResponse(message, json_dumps_params={"ensure_ascii": False, "sort_keys": True, "indent": 4})


def conf_setting_get_api(request):
    """
    通过api获取配置文件
    :param request:
    :return: json message
    """
    if request.method == "GET":
        current_token = get_token()
        token = request.GET.get("token", None)
        if token:
            token = encryption(token)
        server_id = request.GET.get("server_id", None)
        project_id = request.GET.get("project_id_temp", None)
        if token == current_token:
            if server_id and project_id:
                try:
                    # conf_setting_info = models.ConfSettingCenter.objects.filter(b_project_id=project_id, server_id=server_id).first()
                    # conf_setting_message = json.loads(conf_setting_info.setting_content)
                    conf_json_path = os.path.join(BASE_DIR, "static/super_cmdb/agent_file", "conf_json")
                    if not os.path.exists(conf_json_path): os.makedirs(conf_json_path)
                    conf_json_file_path = os.path.join(conf_json_path, "%s_%s.json" % (project_id, server_id))
                    with open(conf_json_file_path, "r", encoding="utf-8") as conf_json_file_obj:
                        conf_setting_message = json.loads(conf_json_file_obj.read())
                except Exception as e:
                    logger.error(e)
                    logger.error('异常文件：%s ,异常行号：%s' % (
                        e.__traceback__.tb_frame.f_globals['__file__'], e.__traceback__.tb_lineno))
                    conf_setting_message = {"code": 1, "msg": "获取配置文件失败,ERR: %s" % e}
        else:
            conf_setting_message = {"code": 1, "msg": "认证失败"}
        return JsonResponse(conf_setting_message,
                            json_dumps_params={"ensure_ascii": False, "sort_keys": True, "indent": 4})

def demo(request):
    if request.method == "GET":
        return render(request, "course/基于多项目多分区多应用的配置中心v2的使用教程.html")
